#include <iostream>
#include <event2/event.h>
#include  <event2/bufferevent.h>
#include <string.h>
#include <arpa/inet.h>
#ifndef _WIN32
#include <signal.h>
#endif
using namespace std;

static int sendCount = 0;

void read_cb(struct bufferevent *bev, void *ctx){
        cout<<"[client read]"<<endl;
}
void write_cb(struct bufferevent *bev, void *ctx){
        cout<<"[client write]"<<endl;
        FILE *fp = (FILE *)ctx;
        char data[1024] = {0};
        int len = fread(data, 1, sizeof(data)-1, fp);
        if(len <= 0){
                //读到结尾或者文件出错
                fclose(fp);
                //立刻清理, 可能会造成数据没有发送结束 所以本能在这里清理
                //bufferevent_free(bev);
                bufferevent_disable(bev, EV_WRITE);
                return;
        }
        sendCount+=len;
        //写入buffer
        bufferevent_write(bev, data, len);
} 
void event_cb(struct bufferevent *bev, short what, void *ctx){
        cout<<"[client event]"<<endl;
        //读取超时时间发生后，数据读取停止
        if(what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING){
                cout<<"BEV_EVENT_READING BEV_EVENT_TIMEOUT "<<endl;
                bufferevent_free(bev);
                return ;
        }else if(what & BEV_EVENT_ERROR){ //出错
                bufferevent_free(bev);
                return;
        }else if(what & BEV_EVENT_CONNECTED){//连接成功
                cout<<"BEV_EVENT_CONNECTED"<<endl;
                //触发write
                bufferevent_trigger(bev, EV_WRITE, 0);
                return ;
        }else if(what & BEV_EVENT_EOF){ //服务端的主动关闭了客户端的事件要进来
                cout<<"BEV_EVENT_EOF"<<endl;
                bufferevent_free(bev);
                cout<<sendCount<<endl;
                return ;
        }
}
int main(int argc, char const *argv[])
{
#ifdef _WIN32
        //初始化socket库
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
#else
        //忽略管道信号 发送数据给已关闭的socket
        if(signal(SIGPIPE,SIG_IGN) == SIG_IGN){
                return 1;
        }
#endif
        //要求: 发送当前代码文件给服务器 服务器显示文件
        event_base *base = event_base_new();

        //buffer调用客户端代码
        //-1 内部创建socket
        bufferevent *bev = bufferevent_socket_new(base, -1,  BEV_OPT_CLOSE_ON_FREE);
        
        sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(8080);
        evutil_inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr.s_addr);

        FILE *fp = fopen("11_test_buffer_server_read_file.cpp", "rb");

        //设置回调函数
        bufferevent_setcb(bev,  read_cb, write_cb, event_cb, fp);
        bufferevent_enable(bev, EV_READ|EV_WRITE);
        
        int ret = bufferevent_socket_connect(bev, (sockaddr *)&sin, sizeof(sin));
        if(ret != 0){
                cout<<"connect failed"<<endl;
        }
        
        event_base_dispatch(base);

        event_base_free(base);
        return 0;
}
